#include <sqlite3.h>
#include <stdio.h>

/*
	功能：
		我们从表中读取图像数据并将其写入另一个文件，
		我们称之为 .Imageswoman2.jpg

		gcc -o read_image read_image.c -lsqlite3
		./read_image
*/

int main(void) {

    //我们以写入模式打开一个二进制文件。数据库中的数据将写入文件。
    FILE *fp = fopen("./images/woman.jpg", "wb");
    
    if (fp == NULL) {
        
        fprintf(stderr, "Cannot open image file\n");    
        
        return 1;
    }    
    
    sqlite3 *db;
    char *err_msg = 0;
    
    int rc = sqlite3_open("test.db", &db);
    
    if (rc != SQLITE_OK) {
        
        fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        
        return 1;
    }

    //此 SQL 语句从“图像”表中选择数据。我们从第一行获取二进制数据。
    char *sql = "SELECT Data FROM Images WHERE Id = 1";
        
    sqlite3_stmt *pStmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &pStmt, 0);
    
    if (rc != SQLITE_OK ) {
        
        fprintf(stderr, "Failed to prepare statement\n");
        fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
        
        sqlite3_close(db);
        
        return 1;
    } 
    
    rc = sqlite3_step(pStmt);
    
    int bytes = 0;

    //该函数返回 BLOB 中的字节数。sqlite3_column_bytes()
    if (rc == SQLITE_ROW) {

        bytes = sqlite3_column_bytes(pStmt, 0);
        printf("图片大小:%dB\n",bytes);
    }

    //二进制数据将与函数一起写入文件。
    //该函数返回指向所选二进制数据的指针。fwrite()sqlite3_column_blob()
    fwrite(sqlite3_column_blob(pStmt, 0), bytes, 1, fp);

	//该函数检查是否设置了与流关联的错误指示器。ferror()
    if (ferror(fp)) {            
        
        fprintf(stderr, "fwrite() failed\n");

        return 1;      
    }  
    
    int r = fclose(fp);

    if (r == EOF) {
        fprintf(stderr, "Cannot close file handler\n");
    }       
    
    rc = sqlite3_finalize(pStmt);   

    sqlite3_close(db);
    
    return 0;
}    

